package com.bjb.vr.common.service;

import cn.hutool.core.lang.UUID;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjb.vr.common.ao.UmsAccountAo;
import com.bjb.vr.common.constant.*;
import com.bjb.vr.common.dto.*;
import com.bjb.vr.common.mapper.*;
import com.bjb.vr.common.utils.JwtTokenUtil;
import com.bjb.vr.common.utils.RedisUtil;
import com.bjb.vr.common.utils.ThreadLocalUtil;
import com.bjb.vr.common.vo.UmsAccountVo;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * @author admin
 * @description 针对表【ums_opt_account(后台账户表)】的数据库操作Service实现
 * @createDate 2022-09-06 14:54:20
 */
@Service
public class UmsOptAccountService extends ServiceImpl<UmsOptAccountMapper, UmsOptAccount> {

    private PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private UmsOptAccountMapper optAccountMapper;

    @Resource
    private UmsOptRoleMapper optRoleMapper;

    @Resource
    private UmsOptUserRoleMapper optUserRoleMapper;

    @Resource
    private SysTenantService tenantService;

    @Resource
    private SysTenantMapper sysTenantMapper;

    @Resource
    private SysConfigMapper sysConfigMapper;

    /**
     * 更新用户登录信息
     *
     * @param username
     */
    public void updateLoginTime(String username, LocalDateTime loginTime) {
        LambdaQueryWrapper<UmsOptAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(username), UmsOptAccount::getUsername, username);
        UmsOptAccount optAccount = new UmsOptAccount();
        optAccount.setLoginTime(loginTime);
        this.update(optAccount, queryWrapper);
    }

    /**
     * 查询用户信息
     *
     * @param umsAccountAo
     * @return
     */
    public UmsAccountVo getAccountInfo(UmsAccountAo umsAccountAo) {
        // 开启放行
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        Claims claims = JwtTokenUtil.parseJWT(umsAccountAo.getAuthorization());
        String username = String.valueOf(claims.get(TokenConstants.TOKEN_USERNAME));

        // 查询缓存--运营端
        String refreshTokenId = SecureUtil.md5(username).toUpperCase();
        UmsOptAccount optAccount = (UmsOptAccount) redisUtil.hget(TokenConstants.LOGIN_OPT_TOKEN_KEY + refreshTokenId, TokenConstants.TOKEN_USERNAME);

        // 查询数据库--运营端
        if (Objects.isNull(optAccount)) {
            LambdaQueryWrapper<UmsOptAccount> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(StringUtils.isNotBlank(umsAccountAo.getUserName()), UmsOptAccount::getUsername, umsAccountAo.getUserName());
            queryWrapper.eq(StringUtils.isNotBlank(umsAccountAo.getAuthorization()), UmsOptAccount::getUsername, username);
            optAccount = this.getOne(queryWrapper);
        }

        UmsAccountVo umsAccountVo = new UmsAccountVo();
        BeanUtils.copyProperties(optAccount, umsAccountVo);
        umsAccountVo.setPassword("[PROTECTED]");
        umsAccountVo.setLoginType(LoginConstant.OPERATION);

        // 放入线程变量
        ThreadLocalUtil.set(ThreadLocalConstant.USER_ACCOUNT_INFO, umsAccountVo);

        // 关闭放行
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);
        return umsAccountVo;
    }

    /**
     * 根据用户名查询账户信息
     *
     * @param userName
     * @return
     */
    public UmsOptAccount getAccountByUsername(String userName) {
        LambdaQueryWrapper<UmsOptAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(userName), UmsOptAccount::getUsername, userName);
        UmsOptAccount optAccount = optAccountMapper.selectOne(queryWrapper);
        return optAccount;
    }

    /**
     * 新增租户--运营端
     *
     * @param umsAccountAo
     * @return
     */
    public Boolean addOperationTenant(UmsAccountAo umsAccountAo) {
        UmsAccountVo threadLocalAccount = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        String creator = threadLocalAccount.getUsername();
        String tenantIdNo = null;

        try {
            // 获取租户ID
            SysTenant tenantInfo = tenantService.queryTenantByTenantName(Constants.OPT_TENANT);
            if (Objects.nonNull(tenantInfo)) {
                tenantIdNo = tenantInfo.getTenantId();
            } else {
                tenantIdNo = UUID.fastUUID().toString().split("-")[4];

                // 添加到租户表
                SysTenant sysTenant = new SysTenant();
                sysTenant.setTenantId(tenantIdNo);
                sysTenant.setTenantName(Constants.OPT_TENANT);
                sysTenant.setParentId(umsAccountAo.getParentId());
                sysTenant.setCategory(Constants.OPT_TENANT_CODE);
                sysTenant.setAddress(umsAccountAo.getAddress());
                sysTenant.setEmail(umsAccountAo.getEmail());

                // 放入线程变量
                threadLocalAccount.setTempTenantId(tenantIdNo);
                ThreadLocalUtil.set(ThreadLocalConstant.USER_ACCOUNT_INFO, threadLocalAccount);
                sysTenantMapper.insert(sysTenant);

                // 2、保存sys_config表
                SysConfig sysConfig = new SysConfig();
                sysConfig.setTenantId(tenantIdNo);
                sysConfigMapper.insert(sysConfig);
            }

            // 3、保存ums_account表、ums_role表、ums_user_role表，默认为管理员
            UmsOptAccount optAccount = new UmsOptAccount();
            optAccount.setTenantId(tenantIdNo);
            optAccount.setUsername(umsAccountAo.getUserName());
            optAccount.setPassword(passwordEncoder.encode(umsAccountAo.getPassword()));
            optAccount.setNickName(umsAccountAo.getNickName());
            optAccount.setSuperMan(RoleConstants.SUPER_IDENTIFY);
            optAccountMapper.insert(optAccount);

            UmsOptRole optRole = new UmsOptRole();
            optRole.setTenantId(tenantIdNo);
            optRole.setRoleName(RoleConstants.SUPER_NAME);
            optRole.setRoleKey(RoleConstants.SUPER_ADMIN);
            optRole.setCreateBy(creator);
            optRole.setRemark(RoleConstants.SUPER_NAME);
            optRoleMapper.insert(optRole);

            UmsOptUserRole optUserRole = new UmsOptUserRole();
            optUserRole.setUserId(optAccount.getUserId());
            optUserRole.setRoleId(optRole.getRoleId());
            optUserRole.setTenantId(tenantIdNo);
            optUserRoleMapper.insert(optUserRole);
            return true;
        } catch (Exception e) {
            log.error("新增运营端端租户失败...");
            return false;
        }
    }

    /**
     * 查询用户名或者昵称是否存在
     *
     * @param umsAccountAo
     * @return
     */
    public List<UmsOptAccount> queryUserInfoByNameOrNickName(UmsAccountAo umsAccountAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        List<UmsOptAccount> optAccounts = optAccountMapper.queryUserInfoByNameOrNickName(umsAccountAo.getUserName(), umsAccountAo.getNickName());
        return optAccounts;
    }

    /**
     * 新增用户
     *
     * @param umsAccountAo
     * @return
     */
    public boolean saveUser(UmsAccountAo umsAccountAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        Assert.hasText(umsAccountAo.getUserName(), "用户名不能为空");
        Assert.hasText(umsAccountAo.getPassword(), "密码不能为空");
        UmsOptAccount optAccount = new UmsOptAccount();
        BeanUtils.copyProperties(umsAccountAo, optAccount);
        optAccount.setPassword(passwordEncoder.encode(umsAccountAo.getPassword()));
        optAccount.setUsername(umsAccountAo.getUserName());
        optAccount.setInitialPass(Constants.NO);

        // 保存用户信息
        boolean result = this.save(optAccount);

        // 更新用户角色信息
        if (umsAccountAo.getRoleId() != null) {
            UmsOptUserRole umsUserRole = new UmsOptUserRole();
            umsUserRole.setUserId(optAccount.getUserId());
            umsUserRole.setRoleId(umsAccountAo.getRoleId());
            optUserRoleMapper.insert(umsUserRole);
        }
        return result;
    }
}




